package cn.touna.jss.modules.third.zhishu;

import cn.touna.risk.api.enums.SystemErrorCodeEnum;
import cn.touna.jss.common.entity.IdCardNameEntity;
import cn.touna.jss.common.exception.ResponseException;
import cn.touna.jss.common.factory.ResponseFactory;
import cn.touna.jss.common.properties.disconf.ZhishuProperties;
import cn.touna.jss.common.util.HttpUtil;
import cn.touna.jss.common.util.ValidUtil;
import cn.touna.jss.modules.adapter.ApiMapping;
import cn.touna.jss.modules.third.zhishu.support.SHAUtil;
import cn.touna.risk.api.domain.Response;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.touna.loan.log.service.TracerContextUtil;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 广州智数
 */
@Service
public class ZhishuService {

    @Autowired
    private ZhishuProperties config;
    private Logger logger = LogManager.getLogger();

    private String getPubKey(String crNo,String priKey) throws Exception {
        String func = "SCsec0001";

        JSONObject body = new JSONObject();
        body.put("corpID",config.getCorpID());
        body.put("priKey",priKey);
        logger.info("request PubKey parmas : {},{}",config.getPubKeyUrl(),body.toJSONString());
        JSONObject resObj = requestData(config.getPubKeyUrl(),crNo,func,null,body);
        logger.info("getPubKey result: {}",resObj.toJSONString());
        checkRespFailed(resObj);
        String pubKey = resObj.getJSONObject("body").getString("pubKey");
        logger.info("pubKey: {}",pubKey);
        return pubKey;
    }

    private JSONObject requestData(String url,String crNo,String func,String accessToken,JSONObject body) throws Exception {
        JSONObject head = new JSONObject();
        head.put("serialID",crNo);
        head.put("func",func);
        if(!StringUtils.isEmpty(accessToken)){
            head.put("accessToken",accessToken);
        }

        String headStr = head.toJSONString();
        String bodyStr = body.toJSONString();
        String hashValue = SHAUtil.toSHA(headStr+bodyStr);// DigestUtils.shaHex(bs);

        Map<String,String> request = new HashMap<>();
        request.put("head",head.toJSONString());
        request.put("body",body.toJSONString());
        request.put("hashValue",hashValue);
        logger.info("{},{}",url, JSON.toJSONString(request));
        String res = HttpUtil.postForm(url,request);
        return JSONObject.parseObject(res);
    }

    /**
     * 检查结果是否返回正常，如果失败，则抛出ServiceException
     * @param resObj
     */
    private void checkRespFailed(JSONObject resObj) throws ResponseException {
        JSONObject resHead = resObj.getJSONObject("head");
        int code = resHead.getInteger("code");
        if(code != 0){
            String msg = resHead.getString("codeInfo");
            logger.error("error result : {}",resObj.toJSONString());
            Response response = ResponseFactory.fail(SystemErrorCodeEnum.JSS_EXTSYSTEM_RESP_ERROR,code + ":"+msg,resObj);
            throw new ResponseException(response);
        }
    }

    private String getAccessToken(String crNo) throws Exception {
        //准备参数
        String func = "SCsec0002";
        String priKey = UUID.randomUUID().toString().replace("-","").toUpperCase();
        String pubKey = getPubKey(crNo,priKey);

        //计算sign
        String signBefore = priKey + config.getAppsecrect() + pubKey;
        String sign = DigestUtils.md5Hex(signBefore);

        JSONObject body = new JSONObject();
        body.put("corpID",config.getCorpID());
        body.put("pubKey",pubKey);
        body.put("signMsg",sign);
        logger.info("request accessToken params :{},{}",config.getTokenUrl(),body.toJSONString());
        JSONObject resObj = requestData(config.getTokenUrl(),crNo,func,null,body);
        checkRespFailed(resObj);
        return resObj.getJSONObject("body").getString("accessToken");
    }

    private Response requestData(String url,String func,JSONObject body){
        String crNo = TracerContextUtil.getTraceId();
        String accessToken;
        try {
            accessToken = getAccessToken(crNo);
        }catch (ResponseException e){
            logger.error(e.getMessage(),e);
            return e.getResponse();
        }catch (Exception e) {
            logger.error(e.getMessage(),e);
            return ResponseFactory.fail(SystemErrorCodeEnum.JSS_SYSTEM_ERROR,e.getMessage());
        }

        JSONObject resObj;
        try {
            resObj = requestData(url,crNo,func,accessToken,body);
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            return ResponseFactory.fail(SystemErrorCodeEnum.JSS_SYSTEM_ERROR,e.getMessage());
        }

        try{
            checkRespFailed(resObj);
        }catch (ResponseException e) {
            return e.getResponse();
        }
        return ResponseFactory.success(resObj);
    }

    /**
     * 近期消费能力查询接口
     * @param request
     * @return
     */
    @ApiMapping(value = "zhishu.zxdebtcapConsume",desc = "广州智数.近期消费能力查询接口")
    public Response zxdebtcapConsume(IdCardNameEntity request){
        Response response = ValidUtil.valid(request);
        if(response != null)
            return response;

        String func = "SCdtcp001";
        JSONObject body = new JSONObject();
        body.put("encryptType",config.getEncryptType());
        body.put("name",request.getName());
        body.put("idCard",request.getIdCard());
        body.put("idCardSuffix",0);
        body.put("idType","");

        return requestData(config.getZxdebtcapConsumeUrl(),func,body);
    }
}
